#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <poll.h>
#include <errno.h>
#include "Socket.hpp"
#include "Logger.hpp"
#include "InetAddr.hpp"
#include <unistd.h>



class SelectServer
{
    inline static const int default_size = sizeof(fd_set) * 8;//理论上select可以检测1024个(位图结构中的fd):0~1023
    inline static const int default_fd = 0;//默认标为0，表示不存在
public:
    SelectServer(uint16_t port = 8080):_listensock(std::make_unique<TcpSocket>())
    {
        //RAII风格
        _listensock->BuildListenSocketMethod(port);
        
        struct pollfd listen_sock = {_listensock->SockFd(),POLLIN,0};
        _helper_arr.push_back(listen_sock);
    }


    void Accept(int pos)
    {
        InetAddr client;
        socklen_t len = client.Len();
        int sockfd = _helper_arr[pos].fd;
        int fd = accept(_listensock->SockFd(),(struct sockaddr*)&client.Addr(),&len);
        if(fd < 0)
            LOG(LogLevel::ERROR) << "accept error";
        else
        {
            LOG(LogLevel::INFO) << "accept success";
            struct pollfd sock = {fd,POLLIN,0};
            _helper_arr.push_back(sock);
        }
    }
    
    void Recv(int pos)
    {
        int buffer[1024] = {0};
        int sockfd = _helper_arr[pos].fd;
        int n = recv(sockfd,buffer,sizeof(buffer) - 1,0);//等待不再由recv完成
        if(n > 0)
        {
            LOG(LogLevel::INFO) << "recv success";
            buffer[n] = 0;
            send(sockfd,buffer,n,0);
        }
        else if(n == 0)
        {
            LOG(LogLevel::INFO) << "client quit";
            _helper_arr.erase(_helper_arr.begin() + pos);
            close(sockfd);
        }
        else
        {
            LOG(LogLevel::ERROR) << "recv error";
        }
    }
    void EventDispatch()
    {
        for(int i = 0;i < _helper_arr.size();i++)
        {
            if(_helper_arr[i].fd == _listensock->SockFd() && (_helper_arr[i].revents & POLLIN))
                Accept(i);
            else if(_helper_arr[i].revents & POLLIN)
                Recv(i);
        }
    }
    void Run()
    {
        struct timeval t = {5,0};
        while(true)
        {
            int n = poll(&_helper_arr[0],_helper_arr.size(),-1);//给负数，阻塞式等待:negative number->毫秒
            if(n > 0)
            {
                LOG(LogLevel::INFO) << "poll success";
                //进行任务派发
                EventDispatch();
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << "poll timeout";
                continue;
            }
            else 
            {
                //如果被信号中断了，那么重来一次
                if(errno == EINTR)
                    continue;                
                else
                {
                    LOG(LogLevel::ERROR) << "poll error";
                    exit(errno); 
                }
            }
        }
    }

    

    ~SelectServer()
    {}
private:
    std::unique_ptr<Socket> _listensock;
    std::vector<struct pollfd> _helper_arr;
};
